package com.stxx.stiot2.service.impl;

import cn.hutool.core.util.StrUtil;
import com.stxx.framwork.domain.model.PageQuery;
import com.stxx.framwork.domain.model.PageResult;
import com.stxx.framwork.utils.StoreUtils;
import com.stxx.stiot2.constants.RedisKeys;
import com.stxx.stiot2.domain.Scene;
import com.stxx.stiot2.domain.Terminal;
import com.stxx.stiot2.domain.ext.SignalEx;
import com.stxx.stiot2.external.RedisServer;
import com.stxx.stiot2.service.SceneService;
import com.stxx.stiot2.service.TerminalService;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.sql.SqlBuilder;

import java.sql.SQLException;
import java.util.*;

/**
 * @author Fuzhenlei
 * @date 2025/01/15 16:41
 */
@Component
public class SceneServiceImpl implements SceneService{
    private final static Map<String, List<Scene>> sceneCache = new HashMap<>();
    private final static String cache_prefix_profile = "p_";
    private final static String cache_prefix_terminal = "t_";
    private static long sceneVersion = 0;
    @Inject
    StoreUtils storeUtils;
    @Inject
    TerminalService terminalService;
    @Inject
    RedisServer redisServer;

    private void checkVersion(){
        Long v = redisServer.getValue(RedisKeys.scene_version,Long.class);
        if(v == null){
            v= 0L;
        }
        if(v==sceneVersion){
            return;
        }
        sceneVersion = v;
        sceneCache.clear();
    }

    private void updateVersion(){
        sceneVersion = System.currentTimeMillis();
        redisServer.setValue(RedisKeys.scene_version,sceneVersion);
        sceneCache.clear();
    }



    @Override
    public Scene queryById(Integer id) {
        try {
            return storeUtils.selectById(id,Scene.class);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int insert(Scene bean) throws SQLException {
        setGatewayCode(bean);
        validEntityBeforeSave(bean);
        int r = storeUtils.insert(bean);
        updateVersion();
        return r;
    }

    @Override
    public int update(Scene bean) throws SQLException {
        setGatewayCode(bean);
        validEntityBeforeSave(bean);
        int r= storeUtils.update(bean);
        updateVersion();
        return r;
    }
    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Scene bean){
    }

    private void setGatewayCode(Scene bean){
        if(bean.getActionEnable()&&bean.getActionFlow()!=null){
            bean.getActionFlow().forEach(actionFlow->{
                actionFlow.getActions().forEach(item->{
                    Terminal terminal = terminalService.queryById(item.getTerminalCode());
                    if(terminal!=null){
                        item.setGatewayCode(terminal.getGatewayCode());
                    }
                });
            });
        }
    }



    @Override
    public int delete(Integer name) throws SQLException {
        int r= storeUtils.delete(Scene.class, name);
        updateVersion();
        return r;
    }

    @Override
    public int deleteByIds(Integer[] ids) throws SQLException {
        int r = storeUtils.deleteByIds(Scene.class,ids);
        updateVersion();
        return r;
    }

    @Override
    public List<Scene> list(Scene obj) throws SQLException {
        return storeUtils.selectList(Scene.class,obj);
    }

    @Override
    public PageResult<Scene> pageList(Scene obj, PageQuery pageQuery) throws SQLException {
        return storeUtils.selectPageList(Scene.class,obj,pageQuery);
    }
    @Override
    public List<Scene> queryForExec(String profileCode,String terminalCode) {
        List<Scene> scenes = new ArrayList<>();
        List<Scene> temp = this.queryByProfileCode(profileCode);
        if(temp!=null){
            scenes.addAll(temp);
        }
        if(StrUtil.isNotEmpty(terminalCode)){
            temp = this.queryByTerminalCode(terminalCode);
            if(temp!=null){
                scenes.addAll(temp);
            }
        }
        return scenes;
    }

    @Override
    public List<Scene> queryByProfileCode(String profileCode) {
        checkVersion();
        String key = cache_prefix_profile+profileCode;
        if(sceneCache.containsKey(key)){
            return sceneCache.get(key);
        }
        SqlBuilder sb = new SqlBuilder();
        sb.append("select * from "+storeUtils.getTableName(Scene.class)+" where status=1 and trigger_type='TERMINAL' and profile_code=? and (terminal_code='' or terminal_code is null)",profileCode);
        List<Scene> scenes = null;
        try {
            scenes = storeUtils.sql(sb).queryRowList(Scene.class);
            sceneCache.put(key,scenes);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return scenes;
    }

    @Override
    public List<Scene> queryByTerminalCode(String terminalCode) {
        checkVersion();
        String key = cache_prefix_profile+terminalCode;
        if(sceneCache.containsKey(key)){
            return sceneCache.get(key);
        }
        SqlBuilder sb = new SqlBuilder();
        sb.append("select * from "+storeUtils.getTableName(Scene.class)+" where status=1 and trigger_type='TERMINAL' and terminal_code=?",terminalCode);
        List<Scene> scenes = null;
        try {
            scenes = storeUtils.sql(sb).queryRowList(Scene.class);
            sceneCache.put(key,scenes);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return scenes;
    }

    @Override
    public List<Scene> queryByIds(Collection<Integer> ids) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select * from ").append(StoreUtils.getTableName("scene")).append(" where id in (?...)",ids);
        return storeUtils.sql(sb).queryRowList(Scene.class);
    }

    @Override
    public int changeStatus(Integer id, Boolean status) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("update ").append(StoreUtils.getTableName("scene")).append(" set status = ? where id =?",status,id);
        int r= storeUtils.sql(sb).update();
        updateVersion();
        return r;
    }
}
